package com.ljx.funchat.common.interceptor;

import com.ljx.funchat.common.constant.RedisKey;
import com.ljx.funchat.common.exception.HttpErrorEnum;
import com.ljx.funchat.common.utils.RedisUtils;
import com.ljx.funchat.user.service.LoginService;
import com.ljx.funchat.user.service.impl.LoginServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * token拦截器
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    public static final String AUTHORIZATION_SCHEMA = "Bearer ";
    public static final String TOKEN = "token";

    @Autowired
    private LoginService loginService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = getToken(request);
        Long validUid = loginService.getValidUid(token);
        if (Objects.nonNull(validUid)){
            // 用户已登录
            request.setAttribute(TOKEN, validUid);
            // 刷新token的有效期
            RedisUtils.set(RedisKey.getKey(RedisKey.USER_TOKEN, validUid), token, LoginServiceImpl.TOKEN_EXPIRE_TIME, TimeUnit.DAYS);
        } else {
            // 用户未登录
            // 检验是否所公共接口
            boolean isPublic = isPublicURI(request);
            if (!isPublic){
                // 401
                HttpErrorEnum.ACCESS_DENIED.sendHttpError(response);
                return false;
            }
        }

        return true;
    }

    /**
     * 检验是否是公共登录接口
     * @param request
     * @return
     */
    private boolean isPublicURI(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String[] split = requestURI.split("/");
        return split.length > 3 && Arrays.asList(split).contains("public");
    }

    /**
     * 获取token
     * @param request
     * @return
     */
    private String getToken(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        return Optional.ofNullable(token)
                .filter(h -> h.startsWith(AUTHORIZATION_SCHEMA))
                .map(h -> h.replaceFirst(AUTHORIZATION_SCHEMA, ""))
                .orElse(null);
    }
}
